using System;
using System.Drawing;
using MathService;

namespace GDI
{
    public static class PointFExtentions
    {
        public static PointF CreatePoint_Deg(double R, double AngleDeg) { return CreatePoint(R, AngleDeg * Consts.Geometry.ToRad); }

        public static PointF CreatePoint(double R, double Angle)
        {
            double
                sin = Math.Sin(Angle),
                cos = Math.Cos(Angle);
            return new PointF((float)(R * cos), (float)(R * sin));
        }

        public static PointF CreatePoint_Deg(double X, double Y, double AngleDeg)
        {
            return CreatePoint(X, Y, AngleDeg * Consts.Geometry.ToRad);
        }

        public static PointF CreatePoint(double X, double Y, double Angle)
        {
            double
                sin = Math.Sin(Angle),
                cos = Math.Cos(Angle);
            return new PointF((float)(X * cos - Y * sin), (float)(X * sin + Y * cos));
        }

        public static PointF Rotate_Deg(this PointF Point, double AngleDeg) { return Rotate(Point, AngleDeg * Consts.Geometry.ToRad); }

        public static PointF Rotate(this PointF Point, double Angle) { return CreatePoint(Point.X, Point.Y, Angle); }

        public static PointF Add(this PointF p1, PointF p2) { return new PointF(p1.X + p2.X, p1.Y + p2.Y); }

        public static PointF Add(this PointF p1, SizeF Size) { return new PointF(p1.X + Size.Width, p1.Y + Size.Height); }

        public static PointF Add(this PointF p1, float X, float Y) { return new PointF(p1.X + X, p1.Y + Y); }

        public static PointF Add(this PointF p1, float v) { return new PointF(p1.X + v, p1.Y + v); }

        public static PointF Substract(this PointF p1, PointF p2) { return new PointF(p1.X - p2.X, p1.Y - p2.Y); }

        public static PointF Substract(this PointF p1, SizeF Size) { return new PointF(p1.X - Size.Width, p1.Y - Size.Height); }

        public static PointF Substract(this PointF p1, float X, float Y) { return new PointF(p1.X - X, p1.Y - Y); }

        public static PointF Substract(this PointF p1, float v) { return new PointF(p1.X - v, p1.Y - v); }

        public static PointF Multipy(this PointF p, float kx, float ky)
        {
            return new PointF(p.X * kx, p.Y * ky);
        }

        public static PointF Multipy(this PointF p, double kx, double ky)
        {
            return new PointF((float)(p.X * kx), (float)(p.Y * ky));
        }

        public static PointF Multipy(this PointF p, double k)
        {
            return new PointF((float)(p.X * k), (float)(p.Y * k));
        }

        public static SizeF GetSize(this PointF p1, PointF p2) { return new SizeF(Math.Abs(p2.X - p1.X), Math.Abs(p2.Y - p1.Y)); }

        public static RectangleF GetRectangle(this PointF p1, PointF p2)
        {
            var lv_LeftUp = new PointF(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y));
            var lv_Size = p1.GetSize(p2);
            return new RectangleF(lv_LeftUp, lv_Size);
        }

        public static double GetAbs(this PointF p) { return Math.Sqrt(p.X * p.X + p.Y * p.Y); }
        public static double GetAngle(this PointF p) { return Math.Atan2(p.Y, p.X); }

        public static PointF Function(this PointF p, Func<PointF, PointF> f) { return f(p); }
    }
}